
#include "Debug.h"
#include <sstream>
#include <string>
#include <stdlib.h>
#include <sys/stat.h>
#include <libpq-fe.h>
#include <map>
#include <string.h>
#include <glib.h>
#include <assert.h>
#include <unistd.h>
#include <wait.h>
#include "config.h"
//#include "define.h"
#include "CobwebMql.h"

using namespace std;
int  g_expire = 0;
PGconn *g_db = NULL;
CobWebMQL *pDB = NULL;

bool Init(const char* conf)
{
        struct stat st;
        if (lstat(conf, &st) != 0)
        {
                ERRO<<":"<<conf<<" is not exist!"<<endl;
                return false;
        }
        Configure cfg;
        map <string, string > g_Confs;
        g_Confs = cfg.LoadConfInfo(conf);
        cfg.Print();
        if(g_Confs.size() <= 0)
        {
                cerr<<"error to explain conf :"<< conf<<endl;
                return true;
        }
        map <string, string >::iterator iter;
        string dbhost, dbuser, dbpass, dbname;
        if (g_Confs.find("dbhost") != g_Confs.end())
                dbhost = g_Confs["dbhost"];
        if (g_Confs.find("dbuser") != g_Confs.end())
                dbuser = g_Confs["dbuser"];
        if (g_Confs.find("dbpass") != g_Confs.end())
                dbpass = g_Confs["dbpass"];
        if (g_Confs.find("dbname") != g_Confs.end())
		dbname = g_Confs["dbname"];
        string dbport = "5432";
        if (g_Confs.find("dbport") != g_Confs.end())
		dbport = g_Confs["dbport"];

	g_db = PQsetdbLogin(dbhost.c_str(), dbport.c_str(), NULL, NULL, dbname.c_str(), dbuser.c_str(), dbpass.c_str());

	if(PQstatus(g_db) != CONNECTION_OK)
	{
		ERRO << PQerrorMessage(g_db) << endl;
		PQfinish( g_db);
		g_db = NULL;
                return false;
	}
        string smax, dbfile;
        if (g_Confs.find("maxtable") != g_Confs.end())
                smax = g_Confs["maxtable"];

        int imaxt = atoi(smax.c_str());
        if(imaxt < 1)
           imaxt = 1;

        if (g_Confs.find("rdbhost") != g_Confs.end())
                dbhost = g_Confs["rdbhost"];
        if (g_Confs.find("rdbuser") != g_Confs.end())
                dbuser = g_Confs["rdbuser"];
        if (g_Confs.find("rdbpass") != g_Confs.end())
                dbpass = g_Confs["rdbpass"];
        if (g_Confs.find("rdbname") != g_Confs.end())
		dbname = g_Confs["rdbname"];


        pDB = new CobWebMQL(dbhost.c_str(), dbname.c_str(), dbuser.c_str(), dbpass.c_str(), imaxt);
        if(!pDB->Initialize())
             return false;

        string s; 
        if (g_Confs.find("uexpire") != g_Confs.end())
                s = g_Confs["uexpire"];
        g_expire = atoi(s.c_str()); 

        return true;
}
int getmax()
{
	stringstream sql;
	sql <<"select id from user_profile order by id desc limit 1";
	PGresult *result = PQexec(g_db, sql.str().c_str());
	if(PQresultStatus(result) != PGRES_TUPLES_OK)
	{
		cerr << PQerrorMessage(g_db) << endl;
		PQclear(result);
		return -1;
	}
	long rownum = PQntuples(result);
	if (rownum <= 0 )
	{
		PQclear(result);
		return 0;
	}

        int ic = atoi( (char *)PQgetvalue(result, 0, 0) );
       	PQclear(result);
	
	return ic;
}

int update(char * user, long lt)
{
	string val, name;
        long stamp = 0;
	int iret =  pDB->Fetch(user, name, val, stamp);
        if(iret== 1 && stamp <= 1)
               return 0; 

	if(g_db == NULL)
	{
		cerr<<"db connection is NULL"<<endl;
		return -1;
	}

	int u = atoi(user);
	stringstream sql;
	sql <<"select nick, ruid from user_profile where id="<<u;
	PGresult *result = PQexec(g_db, sql.str().c_str());
	if(PQresultStatus(result) != PGRES_TUPLES_OK)
	{
		cerr << PQerrorMessage(g_db) << endl;
		PQclear(result);
		return -1;
	}
	long rownum = PQntuples(result);
	if (rownum <= 0 )
	{
		PQclear(result);
		return 0;
	}
        string sval;

        sql.str("");
        long expire = lt + g_expire;
        name = (char *)PQgetvalue(result, 0, 0);       
        name.append(":");
        name.append((char *)PQgetvalue(result, 0, 1));        

	PQclear(result);
	sql.str(""); 
	sql<<"select u.partnerid, p.nick, p.ruid from user_relation as u, user_profile as p where ownerid ="<<u<<" and class=1 and u.partnerid=p.id";
	DEBUG1(sql.str());
	result = PQexec(g_db, sql.str().c_str());
	if(PQresultStatus(result) != PGRES_TUPLES_OK)
	{
		cerr << PQerrorMessage(g_db) << endl;
		PQclear(result);
		return -1;
	}

	rownum = PQntuples(result);
	DEBUG2("fetch row = ", rownum);
	if (rownum == 0 )
	{
		PQclear(result);
		return 0;
	}

	for (int i = 0; i < rownum; i++)
	{
                sql.str("");
                if(i > 0)
                   sql<<";";
		sql<< (char *)PQgetvalue(result, i, 0) <<":"<< (char *)PQgetvalue(result, i, 1)
                   <<":" << (char *)PQgetvalue(result, i, 2);
		sval.append(sql.str());
	}
	PQclear(result);
        DEBUG1(sval.c_str() );
	if( stamp > 0)
		pDB->Replace(user,(char *)name.c_str(), (char *) sval.c_str(), expire);
	else
		pDB->Save(user, (char *)name.c_str(), (char *) sval.c_str(), expire);
	return rownum;
}

void Shutdown()
{
	if(g_db != NULL){
		PQfinish( g_db);
		g_db = NULL;
	}
        if(pDB != NULL)
           delete pDB; 
}

int sendMsg(int imax)
{
	char buf[1024];
	int len = sprintf(buf,"echo 'max = %d' | mail -s 'cobweb crawler report' lengsh@alibaba-inc.com", imax);
	buf[len] = '\0';
	system( buf);           
        return 0; 
}

int main(int argc, char *argv[])
{

	if(argc < 2)
	{
		cout<<argv[0] << " conf"<<endl;
		return 0;
	}
        int fid = 1;
        if(argc >=3)
             fid = atoi(argv[2]);
        if(fid < 1)
             fid = 1;
	if(!Init(argv[1]))
	{
		cout<<"ERROR" << endl;
		return 0;
	}
	int imax = getmax();
	sendMsg(imax);
	for(int i= fid; i<= imax; i++)
	{
		ostringstream os;
		os << i;
		update((char *)os.str().c_str(), time(NULL));
		if(i%20000 == 9999)
			sendMsg(i);
	}
	Shutdown();
        return 1;
}

